package si.unimb.src.wifisms.control;

import java.io.*;
import java.util.*;

import android.content.Context;
import android.util.Log;
import si.unimb.src.wifisms.entity.*;

/**
 * 
 * @author Ales
 * 
 * Glavni razred, ki se bo serializiral na disk - za potrebe trajnega shranjevanja stanja.
 * Implementira vmesnik Serializable in drzi reference do vseh ostalih podatkov.
 * 
 * Uporabljen vzorec edinec, do katerega dostopamo preko staticnih metod.
 *
 */
public class Database implements Serializable {

	private static final long serialVersionUID = 2744413524852564978L;
	
	// Podatki
	private ArrayList<Account> accounts = new ArrayList<Account>();
	private ArrayList<SMSMessage> messages = new ArrayList<SMSMessage>();
	private Account defaultAccount = null;
	
	// Podatki o shranjevanju
	private static final String FILENAME = "database.ser";
	
	// Edinec (do njega dostopaj izkljucno samo preko metoge getInstance() !)
	private static Database instance = null;
	
	/**
	 * 
	 * Edinec: ne dovolimo ustvarjanja instanc.
	 * 
	 */
	private Database() {}

	/**
	 * 
	 * Deserializacija podatkov iz datoteke.
	 * 
	 * @param context Context od Activity-ja, ki je poklical metodo
	 * @return Ali smo uspesno prebrali iz datoteke ali ne
	 */
	private static boolean readFromFile(Context context) {
	
		try {
			
			// Deserializacija iz datoteke
			FileInputStream fis = context.getApplicationContext().openFileInput(FILENAME);
			ObjectInputStream ois = new ObjectInputStream(fis);
			instance = (Database)ois.readObject();
			ois.close();
			Log.d("HelloWS2", "Branje iz datoteke je bilo uspesno.");
			return true;
		
		} catch(Exception e) {
			
			e.printStackTrace();
			Log.d("HelloWS2", "Branje iz datoteke ni bilo uspesno.");
			return false;
			
		}
		
	}
	
	/**
	 * 
	 * To naj bo edini nacin dostopa do edinca, saj ga ta metoda
	 * po potrebi prebere iz diska.
	 * 
	 * @param context Context od Activity-ja, ki je poklical metodo
	 * @return Instanco razreda Database
	 */
	private static Database getInstance(Context context) {
	
		// Ce instanca se ne obstaja, jo ustvarimo
		if(instance == null) {
		
			// Prvo jo probamo prebrati iz datoteke
			boolean success = readFromFile(context);
			
			// Drugace pa ustvarimo prazno bazo
			if(!success) {
				
				Log.d("HelloWS2", "Ustvarjam novo bazo.");
				instance = new Database();
				
			}
			
		}
		
		return instance;
		
	}
	
	/**
	 * 
	 * Trajno shranimo stanje podatkov (serializacija edinca v datoteko).
	 * 
	 * @param context Context od Activity-ja, ki je poklical metodo
	 * @return Ali je bilo shranjevanje uspesno?
	 */
	public static boolean persist(Context context) {
		
		// Ce instanca ne obstaja, nimamo kaj za narediti
		if(instance == null) {
			
			return false;
			
		}
		
		try {
			
			// Serializacija v datoteko
			FileOutputStream fos = context.getApplicationContext().openFileOutput(FILENAME, Context.MODE_PRIVATE);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(instance);
			oos.close();
			return true;
		
		} catch(Exception e) {
		
			e.printStackTrace();
			return false;
			
		}

	}
	
	// GETTERS/SETTERS
	public static ArrayList<Account> getAccounts(Context context) {
		return getInstance(context).accounts;
	}

	public static void setAccounts(ArrayList<Account> accounts, Context context) {
		getInstance(context).accounts = accounts;
	}

	public static ArrayList<SMSMessage> getMessages(Context context) {
		return getInstance(context).messages;
	}

	public static void setMessages(ArrayList<SMSMessage> messages, Context context) {
		getInstance(context).messages = messages;
	}

	public static void removeSentMessages(Context context) {
		
		ArrayList<SMSMessage> messages = getMessages(context);
		ArrayList<SMSMessage> removeMe = new ArrayList<SMSMessage>();
		
		System.out.println("getMessages: " + getMessages(context).size());

		for(SMSMessage message : messages) {
			
			// Ce je uspesno poslano
			if(message.getStatus() == SMSMessage.STATUS_SENT) {
				
				// Potem da damo v seznam za odstranitev
				removeMe.add(message);
				
			}
			
			System.out.println("message.getStatus(): "+ message.getStatus());
			
		}
		
		// Odstranimo vse poslane
		if(!removeMe.isEmpty()) {
		
			messages.removeAll(removeMe);
			
		}
		
	}

	/**
	 * 
	 * Nastavimo privzeti Account. Metoda poskrbi tudi za shranjevanje v file.
	 * 
	 * @param defaultAccount Kateri Account zelimo da je privzet
	 * @param context Context od Activity-ja, ki je poklical metodo
	 */
	public static void setDefaultAccount(Account defaultAccount, Context context) {
		
		getInstance(context).defaultAccount = defaultAccount;
		persist(context);
		
	}

	/**
	 * 
	 * Dobimo indeks privzetega Accounta.
	 * Ce ni privzetega (ali pa je izbrisan), potem dobimo 0 -> prvi racun
	 * 
	 * @param context Context od Activity-ja, ki je poklical metodo
	 * @return indeks privzetega Accounta
	 */
	public static int getDefaultAccountIndex(Context context) {
		
		Database instanceTmp = getInstance(context);
		int defaultIndex = instanceTmp.accounts.indexOf(instanceTmp.defaultAccount);
		
		if (defaultIndex < 0) {
			return 0;
		} else {
			return defaultIndex;
		}
		
	}
	
}
